// zzSuperheaterSupreme by zzSleepzz
// Copyright 2009,2010 zzSleepzz
//
// Features:
// Version 2.8
// - Handle scenario where spell has been cast causing bank unable to be opened.
// - Fixed banking to ensure correct ore withdrawal for misclicks.
//
// Version 2.7 (9Jan2010)
// - Minor cleanup
// - Adjusted to correct overwithdrawal of primary ore
//
// Version 2.6 (8Jan2010)
// - Automatically disables randoms and restores the original state
//   when the script is stopped.
//
// Version 2.5  (4Jan2010)
// - Trying to fix the problem where the spell was cast, but the ore
//   wasn't clicked and the script is trying to bank unsuccessfully.
// - Tried to fix the conditions where the script would deposit unsmelted
//   ores unnecessarily.
//
// Version 2.4  (4Jan2010)
// - Revised banking support.
//
// Version 2.31 (Dec2009)
// - Tweeked antiban to display magic stat 20% of time AND THEN do
//   smithing, instead of either or.
//
// Version 2.3 (12Nov2009)
// - Correcting banking issues resulting from not waiting long
//   enough and from misclicks.
// - Corrected timing issues with smelting ores like adamantite.
// - Added support to not deposit fire runes in case the player is not
//   using a fire staff.
//
// Version 2.2 (10Nov2009)
// - Since randoms have to be disabled, record the current
//   location.  If we find ourselves more than 20 away,
//   just stop the script.
// - Improved paint.
//
// Version 2.1 (30Oct2009)
// - Fixed some more inconsistencies in the script actions
//   most notably with banking.
//
// Version 2.0 (29Oct2009)
// - Updated to work with new inventory behavior.  Avoids
//   unnecessary cycling into inventory after each cast,
//   BUT REQUIRES RANDOMS TO BE DISABLED!!!
//   Aren't I slick?  ;-P
//
// Version 1.0
// - Ready for prime time
//
// Version 0.03
// - Tried to improve accuracy of inventory handling.
//
// Version 0.02
// - Closes collection box if opened accidentally
// - Updated antiban to not return to previous cursor position.
//
// Version 0.01
// - Built in antiban
// - Superheats every kind of ore
//   needed runes/equipment are available
// - Proggy
//

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Map;

import org.lazygamerz.scripting.api.Game;
import org.lazygamerz.scripting.api.Magic;
import org.rsbot.bot.Bot;
import org.rsbot.event.listeners.PaintListener;
import org.rsbot.script.Script;
import org.rsbot.script.ScriptManifest;
import org.rsbot.script.wrappers.RSInterfaceChild;
import org.rsbot.script.wrappers.RSPlayer;

@ScriptManifest(authors = {"zzSleepzz"},
category = "Smithing",
name = "Superheater Supreme",
version = 2.9,
description =
"<html>"
+ "<head><style type=\"text/css\"> body {background-color: #FFEFD5 </style></head>"
+ "<body>"
+ "<center>"
+ "<b><font size=+2 color=\"blue\"> Superheater Supreme v2.9<br>"
+ "by zzSleepzz</font></b><br>"
+ "<font size=-2>Based on the AutoAlcher script created by Zachafer</font>"
+ "<p>"
+ "<b><i><font color='red'>This script disables randoms to avoid cycling into the inventory tab.  The original state is restored when the script stops normally.</font></i></b>"
+ "<table>"
+ "<tr valign=top>"
+ "<td align=right><b>Instructions:</b></td><td align=left> Start with fire or lava staff weilded and nature runes in inventory.  "
+ "All required ores must be visible in the current bank tab.</td>"
+ "</tr>"
+ "</table>"
+ "<table><tr align=left>"
+ "<br><td align=right><b>Select bar to create:</b></td>"
+ "<td><select name=\"bar\">"
+ "<option value=\"Runite\">Runite</option>"
+ "<option value=\"Adamantite\">Adamantite</option>"
+ "<option value=\"Mithril\">Mithril</option>"
+ "<option value=\"Gold\">Gold</option>"
+ "<option value=\"Silver\">Silver</option>"
+ "<option value=\"Steel\">Steel</option>"
+ "<option value=\"Iron\">Iron</option>"
+ "<option value=\"Bronze\">Bronze</option>"
+ "</select></td>"
+ "</tr>"
+ "<p>"
+ "</center>"
+ "</body>\n"
+ "</html>")
public class zzSuperheater extends Script implements PaintListener {

    boolean debug = false;

    private void debug(String s) {
        if (debug) {
            log(s);
        }
    }
    ScriptManifest props = getClass().getAnnotation(ScriptManifest.class);
    private static final int coalOreID = 453;
    private static final int runeOreID = 451;
    private static final int addyOreID = 449;
    private static final int mithOreID = 447;
    private static final int ironOreID = 440;
    private static final int goldOreID = 444;
    private static final int silverOreID = 442;
    private static final int copperOreID = 436;
    private static final int tinOreID = 438;
    private static final int runeBarID = 2363;
    private static final int addyBarID = 2361;
    private static final int mithBarID = 2359;
    private static final int goldBarID = 2357;
    private static final int silverBarID = 2355;
    private static final int steelBarID = 2353;
    private static final int ironBarID = 2351;
    private static final int bronzeBarID = 2349;
    private static final int natureID = 561;
    private static final int fireID = 554;
    private boolean needToBank = true;
    private boolean randomsState = true;

    public long startTime;
    public int startSmithLevel;
    public int startMagicLevel;
    public int startSmithXP;
    public int startMagicXP;
    public int bar;
    public int ore;
    public int ore2;
    public int ore1ct;
    public int ore2ct;
    public int ore2fact;
    long Time;
    private boolean onStart = true;
    private static final Color statusBoxBG = new Color(162, 80, 45, 100);
    private static final Color statusBoxFG = Color.WHITE;

    public int loop() {
        try {
            while (!game.isLoggedIn() && onStart) {
                wait(100);
            }

            // Antiban will determine intervals of when to run and will
            // just return if pauseAntiban is set.
            zzAntiban();

            if (needToBank) {
                debug("Need to bank");
                int ct = 0;
                boolean banked = false;

                do {
                    banked = bank();
                    wait(random(100, 400));
                    ct++;
                } while (ct < 5 && !banked);

                if (!banked) {
                    log("Out of ore or no supported bank/booth/chest is nearby.  Stopping script.");
                    return -1;
                }

                if (bank.isOpen()) {
                    if (inventory.getCount(ore) > 0 && inventory.getCount(ore2) >= ore2fact) {
                        bank.close();
                        needToBank = false;
                    }
                    return random(300, 400);
                }
            }

            if (bank.isOpen()) {
                bank.close();
                wait(random(350, 450));
            }

            debug("Superheating");
            if (!superheat()) {
                log("Superheat failed.  Stopping script.");
                return -1;
            } else {
                return random(20, 30);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return 1;
    }

    // This should only return false if the bank faild to open.
    public boolean bank() {
        int i = 0;

        // Dismiss the collection box.
        if (iface.get(109).getChild(13).isValid()) {
            iface.clickChild(109, 13);
            wait(random(500, 900));
        }

        // Check if the superheat spell is selected and if so, click the mouse so the
        // spell is dismissed and the bank can be opened.
        if (getMenuActions()[0].contains("Superheat Item")) {
        	mouse.click(true);
            wait(random(200, 350));
        }

        if (!bank.getInterface().isValid()) {
            debug("Opening the bank.");
            bank.open();
            iface.waitForOpen(bank.getInterface(), 1200);
            wait(random(300, 400));

            if (!bank.isOpen()) {
                if (getMenuActions()[0].contains("Walk")) {
                	mouse.click(true);
                }

                return false;
            }
        }

        debug("Bank was successfully opened.");

        // Five tries to ensure we deposit everything except runes and ores
        for (i = 0; i < 5 && inventory.getCountExcept(natureID, fireID, ore, ore2) > 0; i++) {
            debug("Depositing...attempt " + (i + 1) + " of " + 5);
            int invct = inventory.getCount();

            bank.depositAllExcept(natureID, fireID, ore, ore2);

            int ct = 0;
            while (ct < 20 && inventory.getCount() == invct) {
                wait(100);
                ct++;
            }
            wait(random(350, 500));
        }

        for (i = 0; i < 5 && inventory.getCount(ore) > ore1ct; i++) {
            debug("Depositing excess ore1...attempt " + (i + 1) + " of " + 5);
            int invct = inventory.getCount(ore);

            bank.deposit(ore, invct - ore1ct);

            int ct = 0;
            while (ct < 20 && inventory.getCount(ore) == invct) {
                wait(100);
                ct++;
            }
            wait(random(350, 500));
        }

        if (bank.getCount(ore) == 0 || bank.getCount(ore2) < ore2fact) {
            log("Insufficient ore to continue");
            log("Ore 1 count=" + bank.getCount(ore) + ", Ore 2 count=" + bank.getCount(ore2));
            return false;
        }

        if (ore2ct > 0) {
            int x = inventory.getCount(ore2);
            if (x + inventory.getCountExcept(ore2) == 28) {
                for (i = 0; i < 5 && x == inventory.getCount(ore2); i++) // If we got here, our inventory is full of ore2, need to make room.
                {
                    debug("Inventory is full of ore2, making room for ore1...attempt" + (i + 1) + " of " + 5);
                }

                int invct = inventory.getCount();

                bank.deposit(ore2, ore1ct);

                int ct = 0;
                while (ct < 20 && inventory.getCount() == invct) {
                    wait(100);
                    ct++;
                }
                wait(random(350, 500));
            }
        }


        for (i = 0; i < 5 && inventory.getCount(ore) < ore1ct; i++) {
            debug("Withdrawing ore1...attempt " + (i + 1) + " of " + 5);
            if (inventory.getCount() == 28 || inventory.getCount(ore) > ore1ct) {
                bank.depositAllExcept(fireID, natureID);
                int ct = 0;
                while (ct < 20 && (inventory.getCount() == 28 || inventory.getCount(ore) > ore1ct)) {
                    wait(100);
                    ct++;
                }
                wait(random(350, 500));
            }

            if (inventory.getCount(ore) < ore1ct) {
                bank.withdraw(ore, ore1ct - inventory.getCount(ore));

                int ct = 0;
                while (ct < 20 && inventory.getCount(ore) < ore1ct) {
                    wait(100);
                    ct++;
                }
            }

            int ct = inventory.getCount(ore);
            if (ct > ore1ct) {
                bank.deposit(ore, ct - ore1ct);

                int r = 0;
                while (r < 20 && inventory.getCount(ore) != ore1ct) {
                    wait(100);
                    r++;
                }
            }
        }
        wait(random(300, 400));

        for (i = 0; i < 5 && ore2ct > 0 && inventory.getCount(ore2) < ore2ct; i++) {
            debug("Withdrawing ore2...attempt " + (i + 1) + " of " + 5);
            debug("Inventory count is " + inventory.getCount());
            if (inventory.getCount() == 28) {
                bank.depositAllExcept(ore, fireID, natureID);
                int ct = 0;
                while (ct < 20 && inventory.getCount() == 28) {
                    wait(100);
                    ct++;
                }
                wait(random(350, 500));
            }
            debug("Withdrawing ore2 (" + ore2 + ")");
            bank.withdraw(ore2, 0);

            int ct = 0;
            while (ct < 20 && inventory.getCount(ore2) < ore2ct) {
                wait(100);
                ct++;
            }
        }

        // Check to make sure the withdrawals didn't mess up and give us
        // all seondary ore by accident.  If it did, deposit enough to make
        // room to withdraw the primary ore.
        if (inventory.getCount(ore) == 0 && ore2ct > 0) {
            debug("Depositing excess ore2.");

            int invct = inventory.getCount();
            bank.deposit(ore2, ore1ct);

            int ct = 0;
            while (ct < 20 && inventory.getCount() == invct) {
                wait(100);
                ct++;
            }
            wait(random(350, 500));
        }

        bank.close();
        wait(random(500, 650));

        needToBank = false;

        return true;
    }

    // This method checks to see if ore will be needed and if so,
    // sets the needToBank flag.
    //
    // The method takes a boolean that is used to determine if
    // needOre() was called during a superheat cycle and
    // castSpell() has already been called.  This is a special
    // case, as needOre(true) means "do we need ore AFTER we
    // finish casting this spell", rather than do we need more
    // ore NOW.
    public boolean needOre(boolean castActive) {
        int ore1num = inventory.getCount(ore);
        int ore2num = inventory.getCount(ore2);

        if (castActive) {  // Determine if we are going to need ore
            if (bar == runeBarID && (ore2num < 9 || ore1num < 2)) {
                return true;
            } else if (bar == addyBarID && (ore2num < 16 || ore1num < 2)) {
                return true;
            } else if (bar == mithBarID && (ore2num < 8 || ore1num < 2)) {
                return true;
            } else if (bar == goldBarID && ore1num < 2) {
                return true;
            } else if (bar == silverBarID && ore1num < 2) {
                return true;
            } else if (bar == steelBarID && (ore2num < 4 || ore1num < 2)) {
                return true;
            } else if (bar == ironBarID && ore1num < 2) {
                return true;
            } else if (bar == bronzeBarID && (ore1num < 2 || ore2num < 2)) {
                return true;
            }
        } else { // Determine if we need ore NOW.
            if (bar == runeBarID && (ore2num < 8 || ore1num < 1)) {
                return true;
            } else if (bar == addyBarID && (ore2num < 6 || ore1num < 1)) {
                return true;
            } else if (bar == mithBarID && (ore2num < 4 || ore1num < 1)) {
                return true;
            } else if (bar == goldBarID && ore1num == 0) {
                return true;
            } else if (bar == silverBarID && ore1num == 0) {
                return true;
            } else if (bar == steelBarID && (ore2num < 2 || ore1num < 1)) {
                return true;
            } else if (bar == ironBarID && ore1num == 0) {
                return true;
            } else if (bar == bronzeBarID && (ore1num == 0 || ore2num == 0)) {
                return true;
            }

        }

        return false;
    }

    public void onRepaint(Graphics g) {

        if (game.isLoggedIn()) {
            Color PERCBAR = new Color(255, 255, 0, 150);

            long mm = 0, hh = 0;
            int expGained = 0;

            long runmins = mm + (hh * 60);
            long millis = System.currentTimeMillis() - startTime;
            long hours = millis / (1000 * 60 * 60);
            millis -= hours * 1000 * 60 * 60;
            long minutes = millis / (1000 * 60);
            millis -= minutes * 1000 * 60;
            long seconds = millis / 1000;

            int SmithXPChange = skills.getCurrentXP(STAT_SMITHING) - startSmithXP;
            int MagicXPChange = skills.getCurrentXP(STAT_MAGIC) - startMagicXP;

            int SmithLevelChange = skills.getCurrentLvl(STAT_SMITHING) - startSmithLevel;
            int MagicLevelChange = skills.getCurrentLvl(STAT_MAGIC) - startMagicLevel;

            int boxX = 9;
            int boxY = 208;
            int x = boxX + 3;
            int y = boxY;
            int boxwidthbase = 186;
            int boxwidth;

            g.setFont(g.getFont().deriveFont(Font.BOLD + Font.ITALIC));
            g.setColor(statusBoxBG);
            g.fillRoundRect(boxX, boxY, 180, 130, 10, 10);
            g.setColor(Color.ORANGE);
            g.drawString("  " + props.name() + " v" + props.version(), x, y += 16);

            g.setFont(g.getFont().deriveFont(Font.PLAIN));
            g.setColor(statusBoxFG);
            g.drawString("Time running: " + hours + "." + minutes + "." + seconds,
                    x, y += 18);

            g.drawString("Magic Level: "
                    + skills.getCurrentLvl(STAT_MAGIC), x, y += 16);
            g.drawString("Gained " + MagicLevelChange + " levels, " + MagicXPChange
                    + " exp.", x, y += 12);

            //Progress bar from Jacmob's scripts
            g.setColor(Color.RED);
            boxwidth = boxwidthbase;
            g.fill3DRect(x, y += 3, boxwidth - x, 15, true);
            PERCBAR = new Color((int) (255 - Math.floor(2.55 * (double) skills.getPercentToNextLvl(STAT_MAGIC))), 255, 0, 150);
            g.setColor(PERCBAR);
            boxwidth = (boxwidth - x) * skills.getPercentToNextLvl(STAT_MAGIC) / 100;
            g.fill3DRect(x, y, boxwidth, 15, true);

            g.setColor(Color.WHITE);
            g.drawString("XP to level " + (skills.getRealLvl(STAT_MAGIC) + 1) + ":  " + skills.getXPToNextLvl(STAT_MAGIC) + " (" + skills.getPercentToNextLvl(STAT_MAGIC) + "%)", x + 2, y += 12);

            if (runmins > 0 && expGained > 0) {
                float lvlmins = skills.getXPToNextLvl(STAT_MAGIC) / (expGained / runmins);
                g.drawString("Next level in " + (long) lvlmins + " minutes", x, y += 14);
                g.drawString("Magic XP per hour: " + (expGained / runmins) * 60, x, y += 12);
            }


            g.drawString("Smith Level: "
                    + skills.getCurrentLvl(STAT_SMITHING), x, y += 18);
            g.drawString("Gained " + SmithLevelChange + " levels, " + SmithXPChange
                    + " exp.", x, y += 12);

            //Progress bar from Jacmob's scripts
            g.setColor(Color.RED);
            boxwidth = boxwidthbase;
            g.fill3DRect(x, y += 3, boxwidth - x, 15, true);
            PERCBAR = new Color((int) (255 - Math.floor(2.55 * (double) skills.getPercentToNextLvl(STAT_SMITHING))), 255, 0, 150);
            g.setColor(PERCBAR);
            boxwidth = (boxwidth - x) * skills.getPercentToNextLvl(STAT_SMITHING) / 100;
            g.fill3DRect(x, y, boxwidth, 15, true);

            g.setColor(Color.WHITE);
            g.drawString("XP to level " + (skills.getRealLvl(STAT_SMITHING) + 1) + ":  " + skills.getXPToNextLvl(STAT_SMITHING) + " (" + skills.getPercentToNextLvl(STAT_SMITHING) + "%)", x + 2, y += 12);

            if (runmins > 0 && expGained > 0) {
                float lvlmins = skills.getXPToNextLvl(STAT_SMITHING) / (expGained / runmins);
                g.drawString("Next level in " + (long) lvlmins + " minutes", x, y += 14);
                g.drawString("Magic XP per hour: " + (expGained / runmins) * 60, x, y += 12);
            }
        }
    }

    public boolean onStart(Map<String, String> args) {
        randomsState = Bot.disableRandoms;
        Bot.disableRandoms = true;

        onStart = true;

        // Get what bar to make and setup for it
        String baropt = args.get("bar");
        if (baropt == null) {
            log("An invalid selection for the bar to create was made.");
            return false;
        } else if (baropt.equals("Runite")) {
            bar = runeBarID;
            ore = runeOreID;
            ore2 = coalOreID;
            ore1ct = 3;
            ore2fact = 8;
            ore2ct = ore1ct * ore2fact;
        } else if (baropt.equals("Adamantite")) {
            bar = addyBarID;
            ore = addyOreID;
            ore2 = coalOreID;
            ore1ct = 3;
            ore2fact = 7;
            ore2ct = ore1ct * ore2fact;
        } else if (baropt.equals("Mithril")) {
            bar = mithBarID;
            ore = mithOreID;
            ore2 = coalOreID;
            ore1ct = 5;
            ore2fact = 4;
            ore2ct = ore1ct * ore2fact;
        } else if (baropt.equals("Gold")) {
            bar = goldBarID;
            ore = goldOreID;
            ore2 = 0;
            ore1ct = 27;
            ore2fact = 0;
            ore2ct = ore1ct * ore2fact;
        } else if (baropt.equals("Silver")) {
            bar = silverBarID;
            ore = silverOreID;
            ore2 = 0;
            ore1ct = 27;
            ore2fact = 0;
            ore2ct = ore1ct * ore2fact;
        } else if (baropt.equals("Steel")) {
            bar = steelBarID;
            ore = ironOreID;
            ore2 = coalOreID;
            ore1ct = 9;
            ore2fact = 2;
            ore2ct = ore1ct * ore2fact;
        } else if (baropt.equals("Iron")) {
            bar = ironBarID;
            ore = ironOreID;
            ore2 = 0;
            ore1ct = 27;
            ore2fact = 0;
            ore2ct = ore1ct * ore2fact;
        } else if (baropt.equals("Bronze")) {
            bar = bronzeBarID;
            ore = copperOreID;
            ore2 = tinOreID;
            ore1ct = 13;
            ore2fact = 1;
            ore2ct = ore1ct * ore2fact;
        }

        // Establish time for  to run, in 90s-120s
        // intervals.
        Time = System.currentTimeMillis() + random(90000, 120000);

        while (!game.isLoggedIn()) {
            wait(100);
        }
        while (skills.getCurrentXP(STAT_HITPOINTS) == 0) {
            wait(100);
        }

        startTime = System.currentTimeMillis();
        startSmithLevel = skills.getCurrentLvl(STAT_SMITHING);
        startMagicLevel = skills.getCurrentLvl(STAT_MAGIC);
        startSmithXP = skills.getCurrentXP(STAT_SMITHING);
        startMagicXP = skills.getCurrentXP(STAT_MAGIC);

        needToBank = needOre(false);  // See if we need ore NOW

        onStart = false;

        log("Script is starting.");
        return true;
    }

    ;

    public void onFinish() {
        Bot.disableRandoms = randomsState;

        log("Script is stopping.");
    }

    public boolean superheat() {
        int ct = 0;

        /*
        while(game.getCurrentTab()!=Game.tabMAGIC && count<10) {
        debug("Need to open magic tab");
        count++;
        openTab(Game.tabMAGIC);

        int ct=0;
        while (ct<20 && game.getCurrentTab()!=Game.tabMAGIC)  {
        wait(100);
        ct++;
        }
        }

        if (game.getCurrentTab()!=Game.tabMAGIC) {
        return true;
        }
         */
        debug("Casting superheat");
        // Click the magic spell, switches to inventory, so wait for it
        magic.castSpell(Magic.SPELL_SUPERHEAT_ITEM);

        ct = 0;
        while (ct < 100 && (game.getCurrentTab() != Game.tabInventory)) {
            ct++;
            wait(20);
        }
        wait(random(100, 230));  // Wait an additional short time

        debug("Current tab="+game.getCurrentTab());
        debug("Inventory should be open now");
        // The new RunTek5 interface causes RSBot to have to open the
        // inventory interface in order to do stuff like inventory.getCount.
        // castSpell causes the inventory to get opened anyway, so let's
        // see if we can't take advantage of that.
        //
        // This is the time to do any inventory checking an not incur
        // an unnecessary trip to the inventory tab.

        if (!inventory.contains(natureID)) {
            log("Out of nature runes!  Stopping script.");
            return false;
        }

        //This is a failsafe, see if we need to bank right now,
        //before continuing.
        if (needToBank = needOre(false)) {
            return true;
        }

        needToBank = needOre(true);

        if (!inventory.contains(ore)) {
            mouse.click(true);
            return true;
        }

        ct = 0;
        while (ct < 10 && !inventory.clickItem(ore, "Cast")) {
            wait(random(1, 5));
            ct++;
        }

        ct = 0;
        while (ct < 100 && (game.getCurrentTab() != Game.tabMagic)) {
            ct++;
            wait(20);
        }
        wait(random(150, 200));

        return true;
    }

    // This  support is based on WarXperiment's, but
    // doesn't do as many things.  This will:
    //	- move the mouse to a nearby player to see name/level
    //  - move to and right click a nearby player to see the
    //    players there.
    //  - Move the mouse to select the skills tab and hover over
    //    Woodcutting for a short while.
    //  - Move the mouse to the friends list to see who's online
    //  - Mouse actions will move the mouse back to a slightly
    //    different location from where it originally was.
    //  - Won't duplicate the prior action.
    // HoverPlayer 1-30, ClickPlayer 31-60, SkillsTab 61-75, FriendsTab 76-80,
    // EquipmentTab 81-85
    private enum Actions {

        HoverPlayer, ClickPlayer, SkillsTab, FriendsTab,
        EquipmentTab
    }
    private Actions lastAction = Actions.EquipmentTab;
    boolean pauseAntiban = false;

    private void zzAntiban() {
        long currTime = System.currentTimeMillis();

        if (pauseAntiban || (Time > currTime)) {
            return;
        }

        // Set to go off again in another 3-4 minutes.
        Time = currTime + random(180000, 240000);

        int r = random(1, 85);
        if (r < 20) {  // SkillsTab
            if (lastAction == Actions.SkillsTab) {
                zzAntiban();  // retry for diff action.
            }

            int r1 = random(1, 100);
            RSPlayer p = player.getNearestByLevel(1, 130);
            if (r1 < 36) {
                if ((p != null) && p.isOnScreen()) {
                    mouse.move(p.getScreenLocation(), 40, 40);
                    wait(random(450, 650));
                }
            } else if (r1 < 71) {
                if ((p != null) && p.isOnScreen()) {
                    mouse.move(p.getScreenLocation(), 10, 10);
                    wait(random(300, 450));
                    mouse.click(false);
                    wait(random(400, 500));
                }
            }

            if (game.getCurrentTab() != Game.tabStats) {
                RSInterfaceChild tab;
                game.openTab(Game.tabStats);

                if (random(1, 100) < 20) {
                    // Check magic 20% of the time
                    tab = iface.get(320).getChild(128);
                    mouse.move(new Point(tab.getAbsoluteX()
                            + random(2, tab.getWidth() - 1), tab.getAbsoluteY()
                            + random(2, tab.getHeight() - 1)));
                    wait(random(900, 1800));
                }

                tab = iface.get(320).getChild(140);
                mouse.move(new Point(tab.getAbsoluteX()
                        + random(2, tab.getWidth() - 1), tab.getAbsoluteY()
                        + random(2, tab.getHeight() - 1)));
                wait(random(900, 2000));
            }
        } else if (r < 40) {  // FriendsTab
            if (lastAction == Actions.FriendsTab) {
                zzAntiban();  // retry for diff action.
            }

            int r1 = random(1, 100);
            RSPlayer p = player.getNearestByLevel(1, 130);
            if (r1 < 36) {
                if ((p != null) && p.isOnScreen()) {
                    mouse.move(p.getScreenLocation(), 40, 40);
                    wait(random(450, 650));
                }
            } else if (r1 < 71) {
                if ((p != null) && p.isOnScreen()) {
                    mouse.move(p.getScreenLocation(), 10, 10);
                    wait(random(300, 450));
                    mouse.click(false);
                    wait(random(400, 500));
                }
            }

            if (game.getCurrentTab() != Game.tabFriends) {
                game.openTab(Game.tabFriends);
            }
        } else if (r < 50) {  // EquipmentTab
            if (lastAction == Actions.EquipmentTab) {
                zzAntiban();  // retry for diff action.
            }

            int r1 = random(1, 100);
            RSPlayer p = player.getNearestByLevel(1, 130);
            if (r1 < 36) {
                if ((p != null) && p.isOnScreen()) {
                    mouse.move(p.getScreenLocation(), 40, 40);
                    wait(random(450, 650));
                }
            } else if (r1 < 71) {
                if ((p != null) && p.isOnScreen()) {
                    mouse.move(p.getScreenLocation(), 10, 10);
                    wait(random(300, 450));
                    mouse.click(false);
                    wait(random(400, 500));
                }
            }
        }

    }
}
